package com.laf.common.utils;

import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.util.StrUtil;
import com.cloopen.rest.sdk.BodyType;
import com.cloopen.rest.sdk.CCPRestSmsSDK;
import com.laf.common.core.redis.RedisCache;
import com.laf.common.enums.SMSTypeEnum;
import com.laf.common.exception.ServiceException;
import com.laf.common.properties.SMSProperties;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@Slf4j
/**
 * 发送短信和校验短信的工具类
 */
@Component
public class SMSUtil {

    @Autowired
    private SMSProperties smsProperties;

    @Autowired
    private RedisCache redisCache;

    private static CCPRestSmsSDK sdk;

    /**
     * 获取CCPRestSmsSDK
     *
     * @return CCPRestSmsSDK
     */
    @PostConstruct
    private void getCcpRestSmsSDK() {
        String serverIp = "app.cloopen.com";
        //请求端口
        String serverPort = "8883";
        //主账号,登陆云通讯网站后,可在控制台首页看到开发者主账号ACCOUNT SID和主账号令牌AUTH TOKEN
        String accountSId = smsProperties.getAccountSId();
        String accountToken = smsProperties.getAuthToken();
        //请使用管理控制台中已创建应用的APPID
        String appId = smsProperties.getAppId();
        sdk = new CCPRestSmsSDK();
        sdk.init(serverIp, serverPort);
        sdk.setAccount(accountSId, accountToken);
        sdk.setAppId(appId);
        sdk.setBodyType(BodyType.Type_JSON);
    }

    /**
     * 发送短信
     *
     * @param phone       手机号码
     * @param smsTypeEnum 短信类型
     * @return 短信验证码
     */
    public String sendSms(String phone, @NonNull SMSTypeEnum smsTypeEnum) {
        // 如果验证码的有效期在 4 分钟内，不能再次发送
        String key = smsTypeEnum.getKey() + phone;
        long expire = redisCache.getExpire(key);

        // 如果验证码在 2 分钟之内已经发送，不能再次发送
        if (expire >= 3 * 60) {
            throw new ServiceException("验证码已发，请不要重复发送");
        }

        // 发送短信
        log.info(phone + "  发送短信验证码");
        String templateId = "1"; // 使用官方提供的免费模板
        // 生成验证码
        RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
        String code = randomGenerator.generate(); // 验证码
        long expireTime = 5L;  // 有效期
        String[] datas = {code, Long.toString(expireTime)};  // 发送的数据
        // 发送
        HashMap<String, Object> result = sdk.sendTemplateSMS(phone, templateId, datas);
        if ("000000".equals(result.get("statusCode"))) {

            //正常返回输出data包体信息（map） // 将数据存入redis ， 并且设置过期时间
            redisCache.setCacheObject(key, code, Math.toIntExact(expireTime), TimeUnit.MINUTES);
            return code;
        } else {
            log.error("短信发送失败 : {}", phone);
            return null;
        }
    }

    /**
     * 校验短信
     *
     * @param phone       手机号码
     * @param code        验证码
     * @param smsTypeEnum 短信类型
     */
    public void checkSms(String phone, String code, SMSTypeEnum smsTypeEnum) {
        String key = smsTypeEnum.getKey() + phone;
        String redisSms = (String) redisCache.getCacheObject(key);
        if (StrUtil.isBlank(redisSms)) {
            throw new ServiceException("验证码已过期");
        }
        if (!redisSms.equals(code)) {
            throw new ServiceException("验证码错误");
        }
    }

    /**
     * 移除短信
     *
     * @param phone       手机号码
     * @param smsTypeEnum 短信类型
     */
    public void removeSms(String phone, SMSTypeEnum smsTypeEnum) {
        String key = smsTypeEnum.getKey() + phone;
        redisCache.deleteObject(key);
    }


}
